#include <string>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <map>
#include <signal.h>
#include <iostream>
#include <utility>
#include <sstream>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/inet.h>

using namespace std;

const int TIMEOUT = 500;
const int MAXCLINUM = 10000;
const int HEADLENGTH = 12;
const int MAXHANDLE = 10000;

class Agent;
class TCPAgent;
class AgentManager;
class SocketAddr;
class EpollEvent;

const SocketAddr InitAddr( "0", 0 );

struct Head
{
    int srcID;
    int destID;
    int len;
};

struct Message
{
    struct Head MsgHead;
    char *rdptr, *wtptr, *bufptr;
};

class Agent
{
public:
    Agent();
    ~Agent();

    virtual int Read();
    virtual int Write();
    virtual int connect( const SocketAddr& );
    virtual int getOppAddr( SoketAddr& );

    virtual void getID() const;
    virtual uint32_t setID( uint32_t );

protected:
    uint32_t agentID;
    int m_iConnect;
    int m_iConnectTimes;

};

class TCPAgent : public Agent
{
public:
    TCPAgent();
    TCPAgent( const SocketAddr& );
    TCPAgent( const TCPSocket&, const SocketAddr& )

    int Read() override;
    int Write() override;
    int connect( const SocketAddr& ) override;
    int getOppAddr( SocketAddr& ) override;

    void getID() const override;
    uint32_t setID( uint32_t );

protected:
    SocketAddr m_addr;
    TCPSocket  m_socket;
    Message    m_message;
    int        m_len;
};

class SocketAddr
{
public:
    SocketAddr();
    SocketAddr(const char *buf, unsigned short p);
    ~SocketAddr();

    void setAddress( const char*, unsigned short );
    const char* getIP( void ) const
    {
        return m_ip.c_str();
    }

    unsigned getPort( void ) const
    {
        return m_port;
    }
    sockaddr_in getAddr();
    bool getAddr(sockaddr_in &addr);
    void setPort( unsigned short );
;
private:
    string          m_ip;
    unsigned short  m_port;
    string          m_str;
};

class TCPSocket
{
public:
    TCPSocket();
    TCPSocket( int fd );
    ~TCPSocket();

    int generateSocket( void );
    int bind( const SocketAddr& );
    int listen( int q );
    int connect( const SocketAddr& );
    int accept( SocketAddr& );
    int Read( char *buf, size_t len );
    int Write( const char *buf, size_t len );
    int getFd( void ) const;
    int close( void );

    int setNonblock();

private:
    int m_fd;
}
